/*
 * UART Interrupt Example
 * This example demonstrates how to use UART with interrupt reception on ESP32
 * using GPIO20 (RX) and GPIO21 (TX).
 *
 * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp_log.h"

#include "u0_uart.h"

// 配置参数
#define UART_PORT_NUM      UART_NUM_0          // 使用UART0
#define UART_BAUD_RATE     115200              // 波特率
#define UART_TX_GPIO_NUM   21                  // TX引脚
#define UART_RX_GPIO_NUM   20                  // RX引脚
#define UART_RTS_GPIO_NUM  UART_PIN_NO_CHANGE  // 不使用RTS
#define UART_CTS_GPIO_NUM  UART_PIN_NO_CHANGE  // 不使用CTS
#define BUF_SIZE           1024                // 缓冲区大小

// 日志标签
static const char *TAG = "uart0_interrupt_example";

// 接收队列
static QueueHandle_t uart_queue;

/**
 * @brief UART事件处理函数
 * @param event 接收到的UART事件
 */
static void uart_event_task(void *pvParameters)
{
    uart_event_t event;
    uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
    size_t buffered_size;

    for (;;) {
        // 等待UART事件
        if (xQueueReceive(uart_queue, (void *)&event, (TickType_t)portMAX_DELAY)) {
            bzero(data, BUF_SIZE);
            ESP_LOGI(TAG, "uart[%d] event: %d", UART_PORT_NUM, event.type);
            
            switch (event.type) {
                // 接收数据
                case UART_DATA:
                    ESP_LOGI(TAG, "UART_DATA eventAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
                    uart_read_bytes(UART_PORT_NUM, data, event.size, portMAX_DELAY);
                    ESP_LOGI(TAG, "接收到的数据: %s", data);
                    break;

                // 接收缓冲区满
                case UART_FIFO_OVF:
                    ESP_LOGW(TAG, "UART_FIFO_OVF event");
                    uart_flush_input(UART_PORT_NUM);
                    xQueueReset(uart_queue);
                    break;

                // 接收缓冲区超时
                case UART_BUFFER_FULL:
                    ESP_LOGW(TAG, "UART_BUFFER_FULL event");
                    uart_flush_input(UART_PORT_NUM);
                    xQueueReset(uart_queue);
                    break;

                // 中断错误
                case UART_PARITY_ERR:
                    ESP_LOGE(TAG, "UART_PARITY_ERR event");
                    break;

                // 帧错误
                case UART_FRAME_ERR:
                    ESP_LOGE(TAG, "UART_FRAME_ERR event");
                    break;

                // 其他事件
                default:
                    ESP_LOGI(TAG, "其他UART事件: %d", event.type);
                    break;
            }
        }
    }

    free(data);
    data = NULL;
    vTaskDelete(NULL);
}

/**
 * @brief 初始化UART
 */
void uart_init(void)
{
    // 配置UART参数
    uart_config_t uart_config = {
        .baud_rate = UART_BAUD_RATE,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_DEFAULT,
    };

    // 安装UART驱动程序，并启用DMA模式
    ESP_ERROR_CHECK(uart_driver_install(UART_PORT_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart_queue, 0));
    
    // 配置UART参数
    ESP_ERROR_CHECK(uart_param_config(UART_PORT_NUM, &uart_config));
    // 设置UART引脚
    ESP_ERROR_CHECK(uart_set_pin(UART_PORT_NUM, UART_TX_GPIO_NUM, UART_RX_GPIO_NUM, UART_RTS_GPIO_NUM, UART_CTS_GPIO_NUM));

    // 创建UART事件处理任务
    xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, 1, NULL);

    ESP_LOGI(TAG, "UART初始化完成，使用GPIO%d(RX)和GPIO%d(TX)，已启用DMA模式", UART_RX_GPIO_NUM, UART_TX_GPIO_NUM);
}

/**
 * @brief 通过UART发送数据
 * @param data 要发送的数据
 * @param len 数据长度
 * @return 发送的字节数
 */
int uart_send_data(const char *data, size_t len)
{
    return uart_write_bytes(UART_PORT_NUM, data, len);
}

